package com.xiguaji.tiktok.task.blogger.event;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.gugee.tiktok.common.model.dal.blogger.BloggerMainRepository;
import com.gugee.tiktok.common.model.dal.blogger.BloggerRecordRepository;
import com.gugee.tiktok.common.model.mysql.BloggerMain;
import com.gugee.tiktok.common.model.mysql.BloggerRecord;
import com.gugee.tiktok.common.model.spider.blogger.BloggerResponse;
import com.xiguaji.boot.eventbus.Event;
import com.xiguaji.boot.eventbus.EventBusTemplate;
import com.xiguaji.boot.eventbus.IEventListener;
import com.xiguaji.boot.toolkit.ThreadPoolUtils;
import com.xiguaji.tiktok.task.blogger.client.AwemeClient;
import com.xiguaji.tiktok.task.blogger.spider.BloggerSpiderClient;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;

@Slf4j
@Component
public class SaveBloggerRecordEventListener implements IEventListener<SaveBloggerRecordEventListener.SaveBloggerRecordEvent> {
    @Autowired
    BloggerMainRepository bloggerMainRepository;

    @Autowired
    BloggerRecordRepository bloggerRecordRepository;

    @Autowired
    BloggerSpiderClient bloggerSpiderClient;

    @Autowired
    AwemeClient awemeClient;

    @Autowired
    @Lazy
    EventBusTemplate eventBusTemplate;

    @Autowired
    BloggerMain.BloggerMainMapper bloggerMainMapper;

    ForkJoinPool forkJoinPool = ThreadPoolUtils.forkJoinPool(60, "SaveBloggerRecord");

    @SneakyThrows
    @Override
    @AllowConcurrentEvents
    @Subscribe
    public void handle(SaveBloggerRecordEvent event) {
        int dateCode = Integer.parseInt(DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
        if(event.bloggers.size()==1){
            BloggerMain  bloggerMain=event.bloggers.get(0);
            try{
                long start=System.currentTimeMillis();
                run(bloggerMain,dateCode,event);
                if((System.currentTimeMillis()-start)/1000>5) {
                    log.info("*****---->>>>SaveBloggerRecordEvent:[Uid={},use times={}]", bloggerMain.getOUid(), (System.currentTimeMillis() - start) / 1000);
                }
            }catch (Exception e){
                log.error("SaveBloggerRecordError! uid:{}",bloggerMain.getOUid(),e);
            }
            return;
        }

        forkJoinPool.submit(() ->
            event.bloggers.parallelStream().forEach(bloggerMain -> {
                try{
                    long start=System.currentTimeMillis();
                    run(bloggerMain,dateCode,event);
                    if((System.currentTimeMillis()-start)/1000>5) {
                        log.info("*****---->>>>SaveBloggerRecordEvent:[Uid={},use times={}]", bloggerMain.getOUid(), (System.currentTimeMillis() - start) / 1000);
                    }
                }catch (Exception e){
                    log.error("SaveBloggerRecordError! uid:{}",bloggerMain.getOUid(),e);
                }
            })
        ).get();

    }

    public void run (BloggerMain bloggerMain, int dateCode, SaveBloggerRecordEvent event){
        val bloggerRecordOptional = bloggerRecordRepository.findByUidAndDatecode(bloggerMain.getOUid(),dateCode);
        BloggerMain blogger = bloggerMain;

        if(event.isUpdate){
            BloggerResponse response = bloggerSpiderClient.get(bloggerMain.getOUid(), bloggerMain.getORegion());
            blogger = bloggerMainMapper.mapper(response.getUser());
        }

        if(blogger == null){
            return;
        }
        BloggerRecord bloggerRecord;

        if(bloggerRecordOptional.isPresent()){
            bloggerRecord = bloggerRecordOptional.get();
            bloggerRecord.setUpdateBy("SaveBloggerRecord -- Update");
        }else{
            bloggerRecord = new BloggerRecord();
            bloggerRecord.setDatecode(dateCode);
            bloggerRecord.setBloggerId(bloggerMain.getId());
            bloggerRecord.setUid(bloggerMain.getOUid());
            bloggerRecord.setFollowerGrowth(0);
            bloggerRecord.setLikeGrowth(0);
            bloggerRecord.setReviewGrowth(0);
            bloggerRecord.setShareGrowth(0);
            bloggerRecord.setViewGrowth(0);
            bloggerRecord.setCreateBy("SaveBloggerRecord -- Add");
            bloggerRecord.setUpdateBy("SaveBloggerRecord -- Add");
        }
        bloggerRecord.setBloggerType(bloggerMain.getBloggerType());
        bloggerRecord.setAvatar(blogger.getOAvatar168());
        bloggerRecord.setNickname(blogger.getONickname());
        bloggerRecord.setUniqueId(blogger.getOUniqueId());
        bloggerRecord.setScore(bloggerMain.getScore());
        // bloggerRecord.setAwemeCount(blogger.getOAwemeCount());
        bloggerRecord.setFollowerCount(blogger.getOFollowerCount());
        bloggerRecord.setLikeTotalCount(blogger.getOTotalFavorited());


        // 当前90天视频总数据（今天打卡数据）
        val bloggerRecordAwemeExtendDto = awemeClient.getBloggerRecordAwemeExtendDto(blogger.getOUid());
        bloggerRecord.setLikeCount(bloggerRecordAwemeExtendDto.getLikesCount());
        bloggerRecord.setViewCount(bloggerRecordAwemeExtendDto.getViewsCount());
        bloggerRecord.setReviewCount(bloggerRecordAwemeExtendDto.getReviewsCount());
        bloggerRecord.setShareCount(bloggerRecordAwemeExtendDto.getShareCount());
        bloggerRecord.setAwemeCount(bloggerRecordAwemeExtendDto.getAwemeCount());

        LocalDateTime dateTime = DateUtil.parseLocalDateTime(String.valueOf(dateCode),DatePattern.PURE_DATE_PATTERN);
        val yesterdayCode = DateUtil.format(dateTime.minusDays(1),DatePattern.PURE_DATE_PATTERN);
        val yesterdayBloggerRecordOptional = bloggerRecordRepository.
                findByUidAndDatecode(bloggerMain.getOUid(), Integer.parseInt(yesterdayCode));
        if(yesterdayBloggerRecordOptional.isPresent()){
            bloggerRecord.setFollowerGrowth(bloggerRecord.getFollowerCount() -
                    yesterdayBloggerRecordOptional.get().getFollowerCount());
            bloggerRecord.setLikeTotalCountGrowth(bloggerRecord.getLikeTotalCount()- yesterdayBloggerRecordOptional.get().getLikeTotalCount());

            // 获取91天的数据(今天的数据)
            val curBloggerRecordAwemeExtendDto = awemeClient.getBloggerRecordAwemeExtendDto(blogger.getOUid(),91);

            // 计算增量
            bloggerRecord.setLikeGrowth(curBloggerRecordAwemeExtendDto.getLikesCount() - yesterdayBloggerRecordOptional.get().getLikeCount());
            bloggerRecord.setViewGrowth(curBloggerRecordAwemeExtendDto.getViewsCount() - yesterdayBloggerRecordOptional.get().getViewCount());
            bloggerRecord.setReviewGrowth(curBloggerRecordAwemeExtendDto.getReviewsCount() - yesterdayBloggerRecordOptional.get().getReviewCount());
            bloggerRecord.setShareGrowth(curBloggerRecordAwemeExtendDto.getShareCount() - yesterdayBloggerRecordOptional.get().getShareCount());
        }
        bloggerRecordRepository.save(bloggerRecord);

        bloggerMain.setOFollowerCount(blogger.getOFollowerCount());
        bloggerMain.setOTotalFavorited(blogger.getOTotalFavorited());
        /*var bloggerAwemeExtend = awemeClient.getBloggerAwemeExtend(blogger.getOUid());
        bloggerMain.setOAvgLikes(bloggerAwemeExtend.getAvgLikes());
        bloggerMain.setOAvgViews(bloggerAwemeExtend.getAvgViews());
        bloggerMain.setOAvgReviews(bloggerAwemeExtend.getAvgReviews());
        bloggerMain.setOAvgShare(bloggerAwemeExtend.getAvgShare());
        bloggerMain.setOAwemeCount(bloggerAwemeExtend.getAwemeCount());*/
        bloggerMain.setONickname(blogger.getONickname());
        bloggerMain.setOUniqueId(blogger.getOUniqueId());
        bloggerMainRepository.save(bloggerMain);
        val esSaveBloggerMainEvent = new ESSaveBloggerMainEventListener.ESSaveBloggerMainEvent(event, Arrays.asList(bloggerMain));
        eventBusTemplate.post(esSaveBloggerMainEvent);
    }

    public static class SaveBloggerRecordEvent extends Event {

        public SaveBloggerRecordEvent(Event event, List<BloggerMain> bloggers) {
            super(event, "SaveBloggerRecord");
            this.bloggers = bloggers;
        }

        public SaveBloggerRecordEvent(Event event, List<BloggerMain> bloggers,boolean isUpdate) {
            super(event, "SaveBloggerRecord");
            this.bloggers = bloggers;
            this.isUpdate = isUpdate;
        }

        private List<BloggerMain> bloggers;

        private boolean isUpdate = true;
    }
}
